package view;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

import language.Strings;
import model.DataNormalizate;
import model.OperacoesArquivos;

import org.encog.neural.data.NeuralData;
import org.encog.neural.data.NeuralDataPair;
import org.encog.neural.data.NeuralDataSet;
import org.encog.neural.networks.BasicNetwork;
import org.encog.persist.EncogPersistedCollection;

import util.Constantes;
import util.Util;

public class StartEvaluate extends JFrame {

	private static final long serialVersionUID = 1L;
	private JPanel jContentPane = null;
	private JPanel jPanel = null;
	private JLabel lbOperacao = null;
	private JLabel lbOperacaoTitulo = null;
	private JScrollPane jScrollPane = null;
	private JTable jTable = null;
	private JLabel lbAcertos = null;
	private JLabel lbErros = null;
	private JLabel lbAcertosTitulo = null;
	private JLabel lbErrosTitulo = null;
	private ListSelectionModel listSelectionModel = null;
	private String[] colunasJTable = {Strings.TEXT_LABEL_MA, Strings.TEXT_LABEL_MB, 
			Strings.TEXT_LABEL_AA, Strings.TEXT_LABEL_AB, Strings.TEXT_LABEL_TA, 
			Strings.TEXT_LABEL_TB, Strings.TEXT_LABEL_TD, Strings.TEXT_LABEL_NA,
			Strings.TEXT_LABEL_SAIDA, Strings.TEXT_LABEL_IDEAL, Strings.TEXT_LABEL_Modelo};  //11 colunas
	private DefaultTableModel tbmEval = new DefaultTableModel(null, colunasJTable);
	
	private Evaluate evaluate = null;  //  @jve:decl-index=0:
	private JLabel lbAcertosItens = null;
	private JLabel lbErrosItens = null;
	private JLabel lbQtdItens = null;
	 
			
	public StartEvaluate() {
		super();
		initialize();
	}

	private void initialize() {
		this.setSize(737, 446);
		this.setContentPane(getJContentPane());
		this.setTitle(Strings.TITULO_TESTAR_RNA);
		this.setResizable(false);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.setLocation(
						((Toolkit.getDefaultToolkit().getScreenSize().width / 2) - (this
								.getWidth() / 2)),
						((Toolkit.getDefaultToolkit().getScreenSize().height / 2) - (this
								.getHeight() / 2)));
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing (WindowEvent e) {				
				Principal.JANELA_ABERTA = false;
				dispose();			
			}	
			
			@Override
			public void windowOpened(WindowEvent e) {
				super.windowOpened(e);
				carregaDados();
			}
			
			@Override
			public void windowClosed(WindowEvent e) {
				super.windowClosed(e);
				Principal.JANELA_ABERTA = false;
				dispose();				
			}
			
//			@Override
//			public void windowActivated(WindowEvent e) {
//				super.windowActivated(e);
//				carregaDados();
//			}
		});
	}

	private JPanel getJContentPane() {
		if (jContentPane == null) {
			lbQtdItens = new JLabel();
			lbQtdItens.setBounds(new Rectangle(18, 317, 148, 15));
			lbQtdItens.setText("");
			lbErrosItens = new JLabel();
			lbErrosItens.setBounds(new Rectangle(490, 375, 130, 25));
			lbErrosItens.setText("");
			lbErrosItens.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 17));
			lbErrosItens.setForeground(Color.RED);
			lbAcertosItens = new JLabel();
			lbAcertosItens.setBounds(new Rectangle(490, 330, 130, 25));
			lbAcertosItens.setText("");
			lbAcertosItens.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 17));
			lbAcertosItens.setForeground(new Color(50,205,50));
			lbErrosTitulo = new JLabel();
			lbErrosTitulo.setBounds(new Rectangle(330, 375, 130, 25));
			lbErrosTitulo.setText("");
			lbErrosTitulo.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 17));
			lbErrosTitulo.setForeground(Color.RED);
			lbAcertosTitulo = new JLabel();
			lbAcertosTitulo.setBounds(new Rectangle(330, 330, 130, 25));
			lbAcertosTitulo.setText("");
			lbAcertosTitulo.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 17));
			lbAcertosTitulo.setForeground(new Color(50,205,50));
			lbErros = new JLabel();
			lbErros.setBounds(new Rectangle(200, 375, 110, 25));
			lbErros.setText(Strings.TEXT_LABEL_ERROS + ":");
			lbErros.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 17));
			lbErros.setForeground(Color.RED);
			lbAcertos = new JLabel();
			lbAcertos.setBounds(new Rectangle(200, 330, 110, 25));
			lbAcertos.setText(Strings.TEXT_LABEL_ACERTOS + ":");
			lbAcertos.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 17));
			lbAcertos.setForeground(new Color(50,205,50));
			jContentPane = new JPanel();
			jContentPane.setLayout(null);
			jContentPane.setBackground(Color.WHITE);
			jContentPane.add(getJPanel(), null);
			jContentPane.add(getJScrollPane(), null);
			jContentPane.add(lbAcertos, null);
			jContentPane.add(lbErros, null);
			jContentPane.add(lbAcertosTitulo, null);
			jContentPane.add(lbErrosTitulo, null);
			jContentPane.add(lbAcertosItens, null);
			jContentPane.add(lbErrosItens, null);
			jContentPane.add(lbQtdItens, null);
		}
		return jContentPane;
	}

	private JPanel getJPanel() {
		if (jPanel == null) {
			jPanel = new JPanel();
			jPanel.setLayout(null);
			jPanel.setBounds(new Rectangle(0, 0, 735, 86));
			jPanel.setBackground(new Color(35,35,142));
			lbOperacaoTitulo = new JLabel();
			lbOperacaoTitulo.setText(Strings.TITULO_TESTAR_RNA);
			lbOperacaoTitulo.setBounds(new Rectangle(160, 25, 346, 25));
			lbOperacaoTitulo.setFont(new Font("Arial", Font.BOLD, 18));
			lbOperacaoTitulo.setForeground(Color.WHITE);
			lbOperacao = new JLabel();
			lbOperacao.setText("");
			lbOperacao.setBounds(new Rectangle(17, 25, 130, 25));
			lbOperacao.setFont(new Font("Arial", Font.BOLD, 18));
			lbOperacao.setForeground(Color.WHITE);
			jPanel.add(lbOperacao, null);
			jPanel.add(lbOperacaoTitulo, null);
		}
		return jPanel;
	}

	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setBounds(new Rectangle(17, 100, 700, 200));
			jScrollPane.setViewportView(getJTable());
		}
		return jScrollPane;
	}

	private JTable getJTable() {
		if (jTable == null) {
			jTable = new JTable();
		}
		
		jTable.setModel(tbmEval);
		jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
//		jTable.setCellSelectionEnabled(true);
		jTable.setEnabled(false);
//		jTable.setSelectionBackground(Color.GRAY);
//		jTable.setSelectionForeground(Color.GRAY);
		listSelectionModel = jTable.getSelectionModel();
		
		return jTable;
	}

	public void carregaDados(){
		File trainedNetworkFile = Constantes.TRAINED_NETWORK_FILE_EG;
		
		if(!trainedNetworkFile.exists()){
			String erro = Strings.TEXT_LABEL_ARQUIVO_NAO_ENCONTRADO_MSG + ":\n" + trainedNetworkFile.getAbsolutePath()
						+ "\n\n" + Strings.TEXT_LABEL_REDE_NAO_TREINADA_MSG;
			JOptionPane.showMessageDialog(null, erro, Strings.TEXT_LABEL_ARQUIVO_NAO_ENCONTRADO_MSG, JOptionPane.ERROR_MESSAGE);
			
			Principal.JANELA_ABERTA = false;
			this.dispose();
			return;
		}
		
		File evalCSV = geraArquivoParaEval();
		
		if(!evalCSV.exists()){
			return;
		}
			
		if(!Constantes.MAXIMOS_CSV.exists()){
			return;
		}
		
//		JFileChooser chooser = new JFileChooser();
//		chooser.setCurrentDirectory(Constantes.DIRETORIO_RAIZ);
//		chooser.setMultiSelectionEnabled(false);
//		chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
//		chooser.setFileFilter(UtilitariosGUI.extencao(1));
//		
//		int resp = chooser.showOpenDialog(StartEvaluate.this);
//		
//		if(resp == JFileChooser.APPROVE_OPTION){
//			evalCSV = chooser.getSelectedFile();
			
			if(evaluate == null){
				evaluate = new Evaluate();
			}
								
			boolean evalOk = evaluate.evaluate(evalCSV, trainedNetworkFile);
			
			if(!evalOk){
				String erro = Strings.TEXT_LABEL_ERRO_AVALIACAO_MSG;
				JOptionPane.showMessageDialog(null, erro, "Falha ao avaliar", JOptionPane.ERROR_MESSAGE);
				
				Principal.JANELA_ABERTA = false;
				this.dispose();
				return;
			}
			
//			chooser.setEnabled(false);
//			chooser.setVisible(false);
//		} else if(resp == JFileChooser.CANCEL_OPTION || resp == JFileChooser.ABORT){
//			chooser.setEnabled(false);
//			chooser.setVisible(false);
//			Principal.JANELA_ABERTA = false;
//			this.dispose();
//			return;
//		}		
	}
	
	public File geraArquivoParaEval(){
		File perfilEval = Constantes.PERFIL_EVAL;
		File diretorioDadosColetados = Constantes.DIRETORIO_PERFIL_TESTES_RNA_COLETA_DADOS;
		String[] arquivosColetados = diretorioDadosColetados.list();
		
		List<String> conteudoEval = new ArrayList<String>();
		List<String> conteudoArquivo;
				
		if(arquivosColetados != null){
			for (String nomeDoArquivo : arquivosColetados) {				
				File arquivoCorrente = new File(diretorioDadosColetados, nomeDoArquivo);
				if(arquivoCorrente.isFile() && nomeDoArquivo.startsWith("E")){
					conteudoArquivo = OperacoesArquivos.lerTxt(arquivoCorrente.getAbsolutePath());
					
					for (String item : conteudoArquivo) {
						conteudoEval.add(item);
					}
				}
			}
		} else{
			System.err.println("Is not a directory!");
		}
		
		if(conteudoEval.size() == 0){
			String erroParte1 = Strings.TEXT_LABEL_DIR_VAZIO_MSG + ":\n" + diretorioDadosColetados.getAbsolutePath();						
			JOptionPane.showMessageDialog(null, erroParte1, Strings.TEXT_LABEL_DIR_VAZIO, JOptionPane.ERROR_MESSAGE);
		}
		
		if(perfilEval.exists()){
			perfilEval.delete();
		} 
		
		for (String item : conteudoEval) {
			OperacoesArquivos.salvaDadosArquivoTexto(item, perfilEval.getAbsolutePath(), true);
		}	
		
		return perfilEval;
	}
	
	public class ColorRenderer extends JLabel implements TableCellRenderer {
		Border unselectedBorder = null;
		Border selectedBorder = null;
		boolean isBordered = true;

		public ColorRenderer(boolean isBordered) {
			this.isBordered = isBordered;
			setOpaque(true); // MUST do this for background to show up.
		}

		public Component getTableCellRendererComponent(JTable table,
				Object color, boolean isSelected, boolean hasFocus, int row,
				int column) {
			Color newColor = (Color) color;
			setBackground(newColor);
			if (isBordered) {
				if (isSelected) {
					if (selectedBorder == null) {
						selectedBorder = BorderFactory.createMatteBorder(2, 5,
								2, 5, table.getSelectionBackground());
					}
					setBorder(selectedBorder);
				} else {
					if (unselectedBorder == null) {
						unselectedBorder = BorderFactory.createMatteBorder(2,
								5, 2, 5, table.getBackground());
					}
					setBorder(unselectedBorder);
				}
			}

			setToolTipText("RGB value: " + newColor.getRed() + ", "
					+ newColor.getGreen() + ", " + newColor.getBlue());
			return this;
		}
	}
	
	private class Evaluate {
//		private static int QTD_MOTOS = 0;
//		private static int QTD_VEICULOS_PEQUENOS = 0;
//		private static int QTD_VEICULOS_MEDIOS = 0;
//		private static int QTD_VEICULOS_GRANDES = 0;
		private String modelo;
		private double valorClassificacao;
		DecimalFormat df1 = new DecimalFormat();
				
		public BasicNetwork loadNetwork(File trainedNetworkFile, String networkName){			
			EncogPersistedCollection encog = new EncogPersistedCollection(trainedNetworkFile);
			BasicNetwork network = (BasicNetwork) encog.find(networkName);
			
			return network;
		}
		
		private void outputAproximation(double value){
			double MOTO = 0.2;
			double VEICULO_PEQUENO = 0.4;
			double VEICULO_MEDIO = 0.6;
			double VEICULO_CAMINHAO = 0.8;
			double VEICULO_ONIBUS = 1.0;
			String modelo;
			
			if(value < MOTO){
				value = MOTO;
				modelo = "T";
			} else if( (value < VEICULO_PEQUENO) && 
					(Math.abs(value - MOTO) < Math.abs(value - VEICULO_PEQUENO)) ){
				value = MOTO;
				modelo = "T";
			} else if( (value <= VEICULO_PEQUENO) && 
					(Math.abs(value - MOTO) > Math.abs(value - VEICULO_PEQUENO)) ){
				value = VEICULO_PEQUENO;
				modelo = "P";
			} else if( (value < VEICULO_MEDIO) && 
					(Math.abs(value - VEICULO_PEQUENO) < Math.abs(value - VEICULO_MEDIO)) ){
				value = VEICULO_PEQUENO;
				modelo = "P";
			} else if( (value <= VEICULO_MEDIO) && //
					(Math.abs(value - VEICULO_PEQUENO) > Math.abs(value - VEICULO_MEDIO)) ){
				value = VEICULO_MEDIO;
				modelo = "M";
			} else if( (value < VEICULO_CAMINHAO) && 
					(Math.abs(value - VEICULO_MEDIO) < Math.abs(value - VEICULO_CAMINHAO)) ){
				value = VEICULO_MEDIO;
				modelo = "M";
			} else if( (value <= VEICULO_CAMINHAO) && //
					(Math.abs(value - VEICULO_MEDIO) > Math.abs(value - VEICULO_CAMINHAO)) ){
				value = VEICULO_CAMINHAO;
				modelo = "C";
			} else if( (value < VEICULO_ONIBUS) && 
					(Math.abs(value - VEICULO_CAMINHAO) < Math.abs(value - VEICULO_ONIBUS)) ){
				value = VEICULO_CAMINHAO;
				modelo = "C";
			} else if( (value <= VEICULO_ONIBUS) && //
					(Math.abs(value - VEICULO_CAMINHAO) > Math.abs(value - VEICULO_ONIBUS)) ){
				value = VEICULO_ONIBUS;
				modelo = "O";
			} else{
				value = VEICULO_ONIBUS;
				modelo = "O";
			}
			
			setClassificacao(modelo);
			setValorClassificacao(value);
		}
		
		private void setClassificacao(String modelo) {
			this.modelo = modelo;
		}

		private String getClassificacao() {
			return modelo;
		}
		
		private void setValorClassificacao(double valor) {
			this.valorClassificacao = valor;
		}

		private double getValorClassificacao() {
			return valorClassificacao;
		}
		
		public boolean evaluate(File fileEval, File trainedNetworkFile) {
			boolean valorCorreto;
			String[] resultados = new String[11];
			
			int index = 0;
			int qtdAcertos = 0;
			double porcentagem_de_acertos = 0;
			double porcentagem_de_erros = 0;
			
			String networkName = Constantes.TRAINED_NETWORK_NAME;
			
			BasicNetwork network = loadNetwork(trainedNetworkFile, networkName);
			NeuralDataSet evalSet = Util.loadDataCSV(network, fileEval);		
			
			if( network == null ){
				return false;
			}
			
			DataNormalizate norm = new DataNormalizate();
//			NeuralDataSet dadaSet = Util.loadDataCSV(Constantes.MAXIMOS_CSV);
//			int[] maxValues = norm.getMaxValues(dadaSet); 
			if(!Constantes.MAXIMOS_CSV.exists()){
				return false;
			}
			
			int[] maxValues = OperacoesArquivos.lerMaximos(Constantes.MAXIMOS_CSV.getAbsolutePath());			
			norm.dataNormalizate(evalSet, maxValues);
			
			for (NeuralDataPair pair : evalSet) {						
				final NeuralData output = network.compute(pair.getInput());
				
				double saidaRNA = output.getData(0);
				double saidaIdeal = pair.getIdeal().getData(0);
				
				outputAproximation(saidaRNA);
				
				for (int i = 0; i < resultados.length; i++) {
					if(i < 8){
						df1.applyPattern("0");
						resultados[i] = String.valueOf(df1.format(pair.getInput().getData(i)*maxValues[i]));
					} else if(i == 8){
						df1.applyPattern("0.00");
						resultados[i] = String.valueOf(df1.format(saidaRNA));
					} else if(i == 9){
						resultados[i] = String.valueOf(df1.format(saidaIdeal));
					} else if(i == 10){
						resultados[i] = getClassificacao();
					}
				}
				
				if(getValorClassificacao() == saidaIdeal){
					valorCorreto = true;
					qtdAcertos++;
				} else{
					valorCorreto = false;
				}
				
				preencheTabela(resultados, index, valorCorreto);
								
				index++;					
			}
			
			if(index != 0){
				porcentagem_de_acertos = (Double.valueOf(qtdAcertos) / Double.valueOf(index));
				porcentagem_de_erros = (1 - porcentagem_de_acertos);

				df1.applyPattern("#,##0.00%");
				
				lbAcertosTitulo.setText(df1.format(porcentagem_de_acertos));
				lbAcertosItens.setText(qtdAcertos + " " + Strings.TEXT_LABEL_ITENS);
				lbErrosTitulo.setText((df1.format(porcentagem_de_erros)));
				lbErrosItens.setText(index-qtdAcertos + " " + Strings.TEXT_LABEL_ITENS);
				lbQtdItens.setText(index + " " + Strings.TEXT_LABEL_ITENS);
			}		
			
			return true;
		}

		private void preencheTabela(String[] resultados, int row, boolean valorCorreto) {
			String[] campos = new String[resultados.length];
									
			for (int i = 0; i < resultados.length; i++) {
				tbmEval.addRow(campos);
//				tbmEval.setValueAt(resultados[i], row, i);
				
				if(!valorCorreto){
					tbmEval.setValueAt("**"+resultados[i], row, i);
//					Component c = getJTable().prepareRenderer(getJTable().getCellRenderer(row, i), row, i);
//					c.setBackground(Color.RED);
				} else{
					tbmEval.setValueAt(resultados[i], row, i);
				}
			}
		}
	}

}  //  @jve:decl-index=0:visual-constraint="10,10"